home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / DOCJET.ZIP / data.z / Group Hook.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-18  |  8.3 KB  |  337 lines

  1. /* Copyright (C) 1997-1998, Tall Tree Software Co.
  2.  *
  3.  * This code is provided AS-IS, with no warranty expressed or implied.
  4.  *  in no way shall Tall Tree Software Co. be held liable for damages
  5.  *  brought about by the use of this software.
  6.  */
  7.  
  8. #include <windows.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <assert.h>
  12.  
  13. #include <Rewriter Hook.h>
  14.  
  15. struct GroupMarker {
  16.     int line;
  17.     char *group;
  18. };
  19.  
  20. class SourceFile {
  21.     const char *name;
  22.     int numMarkers;
  23.     int maxMarkers;
  24.     GroupMarker *markers;
  25.  
  26. public:
  27.     void AddMarker( int line, const char *marker );
  28.     const char *GetGroup( int line );
  29.  
  30. private:
  31.     static int numFiles;
  32.     static int maxFiles;
  33.     static SourceFile *sourceFiles;
  34.  
  35. public:
  36.     static SourceFile &Find( const char *file );
  37.     static void Destroy();
  38. };
  39.  
  40. int SourceFile::numFiles = 0;
  41. int SourceFile::maxFiles = 0;
  42. SourceFile *SourceFile::sourceFiles = 0;
  43.  
  44. void SourceFile::AddMarker( int line, const char *marker )
  45. {
  46.     if ( markers == 0 ) {
  47.         maxMarkers = 100;
  48.         markers = (GroupMarker *)malloc( maxMarkers * sizeof(GroupMarker) );
  49.     }
  50.     else if ( numMarkers == maxMarkers ) {
  51.         maxMarkers *= 2;
  52.         markers = (GroupMarker *)realloc( markers,
  53.             maxMarkers * sizeof(GroupMarker) );
  54.     }
  55.     markers[numMarkers].line = line;
  56.     markers[numMarkers].group = strdup( marker );
  57.     ++numMarkers;
  58. }
  59.  
  60. const char *SourceFile::GetGroup( int line )
  61. {
  62.     int i = 0;
  63.     for ( ; i < numMarkers && markers[i].line < line; ++i )
  64.       ;
  65.     if ( i > 0 )
  66.       return( markers[i-1].group );
  67.     else
  68.       return( 0 );
  69. }
  70.  
  71. SourceFile &SourceFile::Find( const char *file )
  72. {
  73.     for ( int i = 0; i < numFiles; ++i ) {
  74.         if ( sourceFiles[i].name == file )
  75.           return( sourceFiles[i] );
  76.     }
  77.     if ( sourceFiles == 0 ) {
  78.         maxFiles = 100;
  79.         sourceFiles = (SourceFile *)malloc
  80.             ( maxFiles * sizeof(SourceFile) );
  81.     }
  82.     else if ( numFiles == maxFiles ) {
  83.         maxFiles *= 2;
  84.         sourceFiles = (SourceFile *)realloc( sourceFiles,
  85.             maxFiles * sizeof(SourceFile) );
  86.     }
  87.     sourceFiles[numFiles].name = file;
  88.     sourceFiles[numFiles].numMarkers = 0;
  89.     sourceFiles[numFiles].maxMarkers = 0;
  90.     sourceFiles[numFiles].markers = 0;
  91.     ++numFiles;
  92.     return( sourceFiles[numFiles-1] );
  93. }
  94.  
  95.  
  96. void SourceFile::Destroy()
  97. {
  98.     for ( int i = 0; i < numFiles; ++i ) {
  99.         for ( int j = 0; j < sourceFiles[i].numMarkers; ++j )
  100.           free( sourceFiles[i].markers[j].group );
  101.         if ( sourceFiles[i].markers != 0 )
  102.           free( sourceFiles[i].markers );
  103.     }
  104.     if ( sourceFiles != 0 ) {
  105.         free( sourceFiles );
  106.         // Let's be anal
  107.         sourceFiles = 0;
  108.         numFiles = 0;
  109.         maxFiles = 0;
  110.     }
  111. }
  112.  
  113.  
  114.  
  115. char *sourceExtensions[] = { "c", "cc", "cpp", "cxx", "h", "hxx", "hpp", "inl",
  116.                  "cls", "bas", "frm", "ctl",
  117.                  "idl",
  118.                  0 };
  119.  
  120. extern "C" DLLEXPORT bool RewriteSource( const char *sourceFile,
  121.                      const char *tmpFile )
  122. {
  123.     // See if this is a C, C++, IDL, or VB file...
  124.     const char *ext = strrchr( sourceFile, '.' );
  125.     assert( ext != 0 );
  126.     if ( ext == 0 )
  127.       return( false );
  128.     ext += 1;
  129.     char **ep = sourceExtensions;
  130.     while ( *ep != 0 && 0 != stricmp( ext, *ep ) )
  131.       ++ep;
  132.     if ( *ep == 0 )
  133.       return( false ); // not a source code file.
  134.  
  135.     // Here we'll scan the source file, looking for group
  136.     //   markers and remembering where we found them.
  137.     FILE *f = fopen( sourceFile, "r" );
  138.     assert( f != 0 );
  139.     if ( f == 0 )
  140.       return( false );
  141.  
  142.     SourceFile *source = &SourceFile::Find( sourceFile );
  143.     char buf[1024];
  144.  
  145.     int line = 0;
  146.     while ( fgets( buf, sizeof(buf), f ) ) {
  147.         ++line;
  148.  
  149.         char *s = buf + strspn( buf, " \t" );
  150.         if ( s[0] == '/' && s[1] == '/' )
  151.           s += 2;
  152.         else if ( s[0] == '/' && s[1] == '*' )
  153.           s += 2;
  154.         else if ( s[0] == '\'' )
  155.           s += 1;
  156.         else if ( 0 == _strnicmp( s, "rem ", 4 ) )
  157.           s += 4;
  158.         else if ( 0 == _strnicmp( s, "rem\t ", 4 ) )
  159.           s += 4;
  160.         else
  161.           continue;
  162.  
  163.         // Okay, we got a comment line.  See if it's a group directive...
  164.         s += strspn( s, " \t" );
  165.         if ( 0 != _strnicmp( s, "group", 5 ) )
  166.           continue;
  167.  
  168.         s += 5;
  169.         s += strspn( s, " \t" );
  170.  
  171.         if ( *s != '=' || *s == ':' )
  172.           continue;
  173.  
  174.         s += 1;
  175.         s += strspn( s, " \t" );
  176.  
  177.         char *end = buf+strlen(buf);
  178.         while ( 0 != strchr( "\n \t", end[-1] ) )
  179.           --end;
  180.             
  181.         if ( end[-1] == '/' && end[-2] == '*' ) {
  182.             end -= 2;
  183.             while ( 0 != strchr( "\n \t", end[-1] ) )
  184.               --end;
  185.         }
  186.  
  187.         *end = '\0';
  188.  
  189.         source->AddMarker( line, s );
  190.     }
  191.  
  192.     fclose( f );
  193.  
  194.     // Now hunt for lines that look like:
  195.     //    // Group=<string>
  196.     // or /* Group=<string> */
  197.     // or '  Group=<string>
  198.  
  199.  
  200.     // This allows you to rewrite a source file before it's sent
  201.     //   to the scanner.  If you decide to rewrite the file, return
  202.     //   a boolean indicating whether you rewrote the file.
  203.     return( false );
  204. }
  205.  
  206.  
  207. // The next bit of code should be retained verbatim.  This is what
  208. //   sets up the chain of hooks.  You must implement either neither
  209. //   or both of SetNextOnObjectFound and OnObjectFound.
  210.  
  211. static HookReportFunction nextOnObjectFound;
  212.  
  213. extern "C" DLLEXPORT
  214. void SetNextOnObjectFound( HookReportFunction onObjectFound )
  215. {
  216.     nextOnObjectFound = onObjectFound;
  217. }
  218.  
  219. Subtype rtfSubtypes[] = {
  220.     { 0, "RTF Overview", PAPER_ID },
  221.     { 0, 0, ABSTRACT_ID }
  222. };
  223.  
  224. Subtype htmlSubtypes[] = {
  225.     { 0, "HTML Overview", PAPER_ID },
  226.     { 0, 0, ABSTRACT_ID }
  227. };
  228.  
  229. Subtype glossarySubtypes[] = {
  230.     { 0, "Overview", GLOSSARY_TERM_ID },
  231.     { 0, 0, ABSTRACT_ID }
  232. };
  233.  
  234. static bool IsOverviewGlossary( const char *p_sourceFile )
  235. {
  236.     const char *s = strrchr( p_sourceFile, '\\' );
  237.     if ( s == 0 )
  238.       s = p_sourceFile;
  239.     else
  240.       s = s+1;
  241.     return( 0 == stricmp( s, "overview.gls" ) );
  242. }
  243.  
  244. static bool IsOverview( const char **p_extras )
  245. {
  246.     while ( 0 != *p_extras ) {
  247.         if ( 0 == stricmp( *p_extras, "overview" ) )
  248.           return( *(p_extras[1]) != '\0' );
  249.         p_extras += 2;
  250.     }
  251.     return( false );
  252. }
  253.  
  254. extern "C" DLLEXPORT void OnObjectFound( const char *p_sourceFile,
  255.                      unsigned int p_commentStartLine,
  256.                      unsigned int p_declStartLine,
  257.                      const char *p_objectName,
  258.                      const Subtype &p_subtype,
  259.                      const char *p_superclass,
  260.                      const char *p_declaration,
  261.                      const char *p_comment,
  262.                      const char *p_body,
  263.                      char const **p_extras )
  264. {
  265.     assert( nextOnObjectFound != 0 );
  266.  
  267.     const char *group = SourceFile::Find( p_sourceFile ).
  268.         GetGroup( p_declStartLine );
  269.  
  270.     if ( IsOverviewGlossary(p_sourceFile ) ) {
  271.         (*nextOnObjectFound)( p_sourceFile, p_commentStartLine,
  272.                       p_declStartLine, p_objectName,
  273.                       glossarySubtypes[0], p_superclass,
  274.                       p_declaration, p_comment,
  275.                       p_body, p_extras );
  276.     }
  277.     else if ( 0 == strcmp( p_subtype.fullname, "RTF Document" ) &&
  278.           IsOverview( p_extras ) ) {
  279.         (*nextOnObjectFound)( p_sourceFile, p_commentStartLine,
  280.                       p_declStartLine, p_objectName,
  281.                       rtfSubtypes[0], p_superclass,
  282.                       p_declaration, p_comment,
  283.                       p_body, p_extras );
  284.     }
  285.     else if ( 0 == strcmp( p_subtype.fullname, "HTML Document" ) &&
  286.           IsOverview( p_extras ) ) {
  287.         (*nextOnObjectFound)( p_sourceFile, p_commentStartLine,
  288.                       p_declStartLine, p_objectName,
  289.                       htmlSubtypes[0], p_superclass,
  290.                       p_declaration, p_comment,
  291.                       p_body, p_extras );
  292.     }
  293.     else if ( group == 0 ) {
  294.         (*nextOnObjectFound)( p_sourceFile, p_commentStartLine,
  295.                       p_declStartLine, p_objectName, p_subtype,
  296.                       p_superclass, p_declaration, p_comment,
  297.                       p_body, p_extras );
  298.     }
  299.     else {
  300.         int l = 0;
  301.         for ( ; p_extras[l] != 0; l += 2 )
  302.           ;
  303.         char const **extras = new char const *[ l + 3 ];
  304.         for ( l = 0; p_extras[l] != 0; l += 2 ) {
  305.             extras[l] = p_extras[l];
  306.             extras[l+1] = p_extras[l+1];
  307.         }
  308.         extras[l] = ATTR_DEFAULT_GROUP;
  309.         extras[l+1] = group;
  310.         extras[l+2] = 0;
  311.         (*nextOnObjectFound)( p_sourceFile, p_commentStartLine,
  312.                       p_declStartLine, p_objectName, p_subtype,
  313.                       p_superclass, p_declaration, p_comment,
  314.                       p_body, extras );
  315.         delete[l+3] extras;
  316.     }
  317. }
  318.  
  319. extern "C" DLLEXPORT void OnScanComplete()
  320. {
  321.     SourceFile::Destroy();
  322. }
  323.  
  324. extern "C" DLLEXPORT const Subtype *AugmentSubtypes
  325.     ( const char *filetype, const Subtype *st )
  326. {
  327.     if ( 0 == strcmp( filetype, "RTF Source" ) )
  328.       return( rtfSubtypes );
  329.     else if ( 0 == strcmp( filetype, "HTML Source" ) )
  330.       return( htmlSubtypes );
  331.     else if ( 0 == strcmp( filetype, "Glossary Source" ) )
  332.       return( glossarySubtypes );
  333.     else
  334.       return( 0 );
  335. }
  336.  
  337.